import Ext from './web_extension';
import { delay } from './utils';
import log from './log';

const calcOffset = (screenTotal, screenOffset, oldOffset, oldSize, newSize, preferStart = false) => {
    const isCloserToStart = preferStart || oldOffset < screenTotal - oldOffset - oldSize;

    log('calcOffset', screenTotal, oldOffset, oldSize, newSize, preferStart);

    if (isCloserToStart) {
        return oldOffset;

        // Note: comment out a smarter position for now
        // if (newSize < oldSize) {
        //   return oldOffset
        // }

        // if (newSize < oldSize + oldOffset - screenOffset) {
        //   return oldSize + oldOffset - newSize
        // }

        // return screenOffset
    }

    if (!isCloserToStart) {
        const oldEndOffset = screenOffset + screenTotal - oldOffset - oldSize;

        return oldSize + oldOffset - newSize;

        // Note: comment out a smarter position for now
        // if (newSize < oldSize) {
        //   return oldSize + oldOffset - newSize
        // }

        // if (newSize < oldSize + oldEndOffset) {
        //   return oldOffset
        // }

        // return screenOffset + screenTotal - newSize
    }
};

// winSize.width
// winSize.height
// state 必须为normal
export function resizeWindow(winId, winSize, screenAvailableRect) {
    const sw = screenAvailableRect.width;
    const sh = screenAvailableRect.height;
    const sx = screenAvailableRect.x;
    const sy = screenAvailableRect.y;

    return Ext.windows.get(winId).then((win) => {
        const lastLeft = win.left;
        const lastTop = win.top;
        const lastWidth = win.width;
        const lastHeight = win.height;

        return Ext.windows.update(winId, { ...winSize, state: 'normal' }).then((win) => {
            const left = calcOffset(sw, sx, lastLeft, lastWidth, win.width);
            const top = calcOffset(sh, sy, lastTop, lastHeight, win.height, true);

            Ext.windows.update(winId, { left, top, state: 'normal' });

            const actual = {
                width: win.width,
                height: win.height,
            };

            return {
                actual,
                desired: winSize,
                diff: ['width', 'height'].filter((key) => actual[key] !== winSize[key]),
            };
        });
    });
}

// pureViewportSize.width
// pureViewportSize.height
// referenceViewportWindowSize.window.width
// referenceViewportWindowSize.window.height
// referenceViewportWindowSize.viewport.width
// referenceViewportWindowSize.viewport.height
export function resizeViewport(winId, pureViewportSize, screenAvailableRect, count = 1) {
    const maxRetry = 2;
    log('resizeViewport, ROUND', count);

    return getWindowSize(winId).then((currentSize) => {
        logWindowSize(currentSize);

        const dx = currentSize.window.width - currentSize.viewport.width;
        const dy = currentSize.window.height - currentSize.viewport.height;

        const newWinSize = {
            width: dx + pureViewportSize.width,
            height: dy + pureViewportSize.height,
        };

        log('size set to', newWinSize);
        return resizeWindow(winId, newWinSize, screenAvailableRect)
            .then(() => getWindowSize(winId))
            .then((newSize) => {
                logWindowSize(newSize);

                const data = {
                    actual: newSize.viewport,
                    desired: pureViewportSize,
                    diff: ['width', 'height'].filter((key) => newSize.viewport[key] !== pureViewportSize[key]),
                };

                if (data.diff.length === 0 || count >= maxRetry) {
                    return data;
                }

                return delay(() => {}, 0).then(() => resizeViewport(winId, pureViewportSize, screenAvailableRect, count + 1));
            });
    });
}

export function resizeViewportOfTab(tabId, pureViewportSize, screenAvailableRect) {
    return Ext.tabs.get(tabId).then((tab) => resizeViewport(tab.windowId, pureViewportSize, screenAvailableRect));
}

// size.window.width
// size.window.height
// size.window.left
// size.window.top
// size.viewport.wdith
// size.viewport.height
export function getWindowSize(winId) {
    return Ext.windows.get(winId, { populate: true }).then((win) => {
        const tab = win.tabs.find((tab) => tab.active);

        return {
            window: {
                width: win.width,
                height: win.height,
                left: win.left,
                top: win.top,
            },
            viewport: {
                width: tab.width,
                height: tab.height,
            },
        };
    });
}

export function getFocusedWindowSize() {
    return Ext.windows.getLastFocused().then((win) => getWindowSize(win.id));
}

function logWindowSize(winSize) {
    log(winSize.window, winSize.viewport);
    log('dx = ', winSize.window.width - winSize.viewport.width);
    log('dy = ', winSize.window.height - winSize.viewport.height);
}
